/*  tBookShelf: TextPlugin
    (C) 2007  TvN (Volodymyr Tarasenko), e-mail: tvntsr@yahoo.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


#ifndef FONT_MANAGER_PLUGINS_HPP
#define FONT_MANAGER_PLUGINS_HPP

#include <string>
#include <functional>
#include <map>

#include "Utils/TextStyle.hpp"

extern "C"
{
#include <ft2build.h>
#include FT_FREETYPE_H
#include <freetype/ftglyph.h>
}

#include "Utils/Area.hpp"

class FontManagerError : public std::exception
{
#define  FONTMANAGERERROR_BUF 256
    std::string msg;
public:
    FontManagerError(int error, const char* where)
        : exception()
    {
        char buf[FONTMANAGERERROR_BUF];
        snprintf(buf, 
                 FONTMANAGERERROR_BUF, 
                 "Font Manager (%s) Error, code %d", 
                 where,
                 error);
        msg = buf;
    };

    FontManagerError(const std::string& error)
        : exception(), msg(error)
    {    };

    virtual ~FontManagerError() throw()
    {}

    virtual const char* what() const throw()
    {
        return msg.c_str();
    }

#undef FONTMANAGERERROR_BUF

};


struct cmpCompare: public std::binary_function<std::string, std::string, bool>
{
    bool
    operator()(const std::string& a, const std::string& b) const
    {
        return strcasecmp(a.c_str(), b.c_str()) < 0;
    }
};

class FontManager
{
    // styles, face
    typedef std::map<std::string, FT_Face, cmpCompare>     FONT_STYLES;
    // font name, styles
    typedef std::map<std::string, FONT_STYLES, cmpCompare> FONTS;
public:
    FontManager();
    ~FontManager();

    void addFont(const std::string& file);

    // Checks is font already loaded, if not and download false returns false,
    // if download true - download font if it was not loadded before
    bool isFontAvailable(const std::string& file, bool download = false);

    void useFont(const std::string& file, bool add = true);

    /// style: "Regular", "Bold", "Italic", "Bold Italic"
    void useFont(const std::string& font_name, const std::string& style);

    void useKerning(bool use = true)
    {
        use_kerning = use;
    }

    // Return rendered number of chars. It could be less than str len 
    // if passed string too long for given output
    int  renderLine(DrawingArea&          area,
                    const PageOrientation orient,
                    const wchar_t*        str,
                    const size_t          font_size,
                    const Align           align);

    int  renderLine(DrawingArea&          area,
                    const PageOrientation orient,
                    const wchar_t*        str,
                    const TextStyle&      style);


    void renderChar(DrawingArea&          area,
                    const PageOrientation orient,
                    const wchar_t&        str,
                    const size_t&         font_size);

    void renderChar(DrawingArea&          area,
                    const PageOrientation orient,
                    const wchar_t&        str,
                    const TextStyle&      style);
    // return max count of chars which could be printed in line with current 
    // font and size
//     int getLineLength()
//     {
//         //:FIXME: implement me pls ;)
//         return 40;
//     }

protected:
    void addCreatedFace(FT_Face face);
    bool drawImage(DrawingArea&          area, 
                   const FT_GlyphSlot    glyph, 
                   const int             start,
                   const PageOrientation orient);

private:
    FT_Library library;
    FONTS      fonts;

    FT_Face    current_face;
    bool       delete_current;
    bool       use_kerning;

    FT_Matrix  rotate_matrix;
    
};


#endif //FONT_MANAGER_PLUGINS_HPP
